/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.inspur.edp.lcm.metadata.servermanager.persistent;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataPackage;
import com.inspur.edp.lcm.metadata.api.service.FileService;
import com.inspur.edp.lcm.metadata.common.FileServiceImp;
import com.inspur.edp.lcm.metadata.common.Utils;
import com.inspur.edp.lcm.metadata.servermanager.util.MetadataUtils;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Classname MetadataPackageRepositoryImp Description TODO Date 2019/8/21 17:04
 *
 * @author zhongchq
 * @version 1.0
 */
public class MetadataPackageRepositoryImp implements MetadataPackageRepository {
    private static final Logger log = LoggerFactory.getLogger(MetadataPackageRepositoryImp.class);

    // @Autowired  //TODO 依赖注入会是null,此类还未被初始化。
    FileService fileService = new FileServiceImp();

    ObjectMapper mapper = Utils.getMapper();

    @Override
    public MetadataPackage getPackageEntity(String packagePath) {
        return null;
    }

    @Override
    public GspMetadata getMetadataFromPackage(String metadataPath) {
        return null;
    }

    @Override
    public HashMap<String, MetadataPackage> retrieveSingleMetadataPackage(String path, String packageName) {
        return null;
    }

    @Override
    public HashMap<String, MetadataPackage> retrieveAllMdPkg(String path) throws IOException {
        HashMap<String, MetadataPackage> packageDic = new HashMap<>();
        retrieveMdPkgRecursively(path, packageDic);
        return packageDic;
    }

    public void retrieveMdPkgRecursively(String path, HashMap<String, MetadataPackage> packageDic) throws IOException {
        if (path.isEmpty() || new File(path).getName().toLowerCase().equals("web")) {
            return;
        }
        List<File> files = fileService.getAllFiles(path);
        if (files.size() > 0) {
            List<File> fileList = new ArrayList<>();
            for (File file : files) {
                if (fileService.getExtension(file.toString()).equals(MetadataUtils.getMetadataPackageExtension())) {
                    fileList.add(file);
                }
            }
            if (fileList != null && fileList.size() > 0) {
                for (File file1 : fileList) {
                    try {
                        MetadataPackage metadataPackage = getMetadataPackage(file1);
                        packageDic.put(Utils.handlePath(file1.toString()), metadataPackage);
                    } catch (IOException e) {
                        e.printStackTrace();
                        //todo
//                        e.getMessage() + ":" + file1.getAbsolutePath()
                        log.error(e.getMessage() + ":" + file1.getAbsolutePath());
                    }
                }
            }
        }
        // 路径中目录
        List<File> dirs = fileService.getDirectorys(path);
        for (int i = 0; i < dirs.size(); i++) {
            retrieveMdPkgRecursively(dirs.get(i).toString(), packageDic);
        }
    }

    @Override
    public MetadataPackage getMetadataPackage(File packageFile) throws IOException {
        String manifestStr = "";
        MetadataPackage metadataPackage;
        StringBuilder sb = new StringBuilder();
        InputStream in = new BufferedInputStream(new FileInputStream(packageFile));
        ZipFile zf = new ZipFile(packageFile);
        Charset utf8 = Charset.forName("UTF-8");
        ZipInputStream zipInputStream = new ZipInputStream(in, utf8);
        ZipEntry zipEntry;
        try {
            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                BufferedReader br = new BufferedReader(
                    new InputStreamReader(zf.getInputStream(zipEntry), "UTF-8"));
                if (zipEntry.toString().equals(MetadataUtils.getManifestFileName())) {
                    String line;
                    while ((line = br.readLine()) != null) {
                        sb.append(line);
                    }
                    manifestStr = sb.toString();
                }
                br.close();
            }
        } catch (IOException e) {
            log.error("Error in reading mdpkg, Package is " + packageFile.getAbsolutePath(), e);
            throw new RuntimeException("Error in reading mdpkg, Package is " + packageFile.getAbsolutePath(), e);
        } finally {
            zipInputStream.close();
            zf.close();
            in.close();
        }
//                        String jsonString = handleJsonString(manifestStr);//TODO可能会引起序列化失败
        try {
            metadataPackage = mapper.readValue(manifestStr, MetadataPackage.class);
            log.debug("元数据包：" + packageFile + "已加载。");
        } catch (Exception e) {
            log.error("元数据包中manifest.json反序列化失败，元数据包为" + packageFile, e);
            throw new RuntimeException("元数据包中manifest.json反序列化失败，元数据包为" + packageFile, e);
        }
        return metadataPackage;
    }

    @Override
    public void getManifestFilesPath(String originalPath, List<String> manifestPath) {

    }

    @Override
    public void getMdpkgFilesPath(String originalPath, List<String> mdpkgPath) {
        File dir = new File(originalPath);
        List<File> paths = fileService.getAllFiles(originalPath);
        if (paths.size() > 0) {
            paths.forEach(path -> {
                String extension = fileService.getExtension(path);
                if (extension.equals(MetadataUtils.getMetadataPackageExtension())) {
                    mdpkgPath.add(handlePath(path.toString()));
                }
            });
            searchChildPath4Mdpkg(originalPath, mdpkgPath, dir);
        } else {
            searchChildPath4Mdpkg(originalPath, mdpkgPath, dir);
        }
    }

    private void searchChildPath4Mdpkg(String originalPath, List<String> mdpkgPath, File dir) {
        List<File> dirs = fileService.getDirectorys(dir.toString());
        if (dirs.size() > 0) {
            for (int i = 0; i < dirs.size(); i++) {
                String temPath = originalPath + "/" + fileService.getFileName(handlePath(dirs.get(i).toString()));
                getMdpkgFilesPath(temPath, mdpkgPath);
            }
        }
    }

    private String handlePath(String path) {
        return path.replace("\\", "/");
    }

    @Override
    public String getCombinePath(String path1, String path2) {
        return null;
    }

    @Override
    public String getDirectoryName(String path) {
        return null;
    }
}
